﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Keepo.Helpers;
using AlbumDesigner.Models.ViewModels;
using System.IO;
using Keepo.Models;
using iTextSharp.text;
using iTextSharp.text.pdf;
using System.Web.Script.Serialization;
using AlbumDesigner.Helpers;
using AlbumDesigner.Models.Enums;

namespace AlbumDesigner.Controllers
{
    public class AdminController : Controller
    {
        private AlbumContext db = new AlbumContext();

        public ActionResult Index()
        {
            var user = UserHelper.CurrentUser();

            //if login
            if (user != null)
            {
                //check if the login user is Admin/Studio/Sales/Photographer
                if (user.UserPermissionId != (int)AlbumUsers.Client)
                {
                    return View();
                }
            }

            return RedirectToAction("Login");
        }

        public ActionResult Login()
        {
            //get list of all Albums
            var albums = db.Albums.Where(m => m.IsRemoved == false).ToList();
            ViewBag.AlbumsList = new SelectList(albums, "AlbumId", "Title");

            return View();
        }

        [HttpPost]
        public ActionResult Login(LoginDataWithUsername loginData)
        {
            if (!ModelState.IsValid)
            {
                return Json(new { Key = false, Value = "הנתונים אינם תקינים." });
            }

            //login this user using the login data - get Key/Value result
            var loginResult = UserHelper.Login(loginData, Response, Session);

            return Json(loginResult);
        }

        [CheckPermission(section = "Admin")]
        public ActionResult SystemStatus()
        {
            var viewModel = new SystemStatusViewModel();

            var currentDrive = new DirectoryInfo(Server.MapPath("~/resources")).Root.Name;
            var drive = DriveInfo.GetDrives().Where(m => m.Name == currentDrive).FirstOrDefault();
            viewModel.DriveName = drive.Name;

            viewModel.FreeSpaceOnDisk = FilesHelper.BytesToMegaBytes(drive.AvailableFreeSpace);

            var directorySize = FilesHelper.GetDirectorySize(Server.MapPath("~/resources"));
            viewModel.ImagesUsage = FilesHelper.BytesToMegaBytes(directorySize);

            //count the users that have been login in the last 5 minutes
            var users = db.Users.Where(m => m.LastLogin != null).ToList();
            var usersOnline = users.Where(m => m.LastLogin.Value > DateTime.Now.AddMinutes(-5));
            viewModel.OnlineUsers = usersOnline.Count();
            viewModel.OnlineUserList = usersOnline.Select(m => new SelectListItem() { Value = m.UserId.ToString(), Text = m.Username }).ToList();

            //get system settings
            var systemSettings = db.SystemSettings.FirstOrDefault();
            viewModel.IsOffline = systemSettings.IsOffline;
            viewModel.OfflineMessage = systemSettings.OfflineMessage;

            return View(viewModel);
        }

        [CheckPermission(section = "Admin")]
        [HttpPost]
        public ActionResult SystemStatus(SystemStatusViewModel data)
        {
            //update the system settings
            var systemSettings = db.SystemSettings.FirstOrDefault();
            systemSettings.IsOffline = data.IsOffline;
            systemSettings.OfflineMessage = data.OfflineMessage;

            db.SaveChanges();

            return RedirectToAction("Index");
        }

        [CheckPermission(section = "Admin")]
        public ActionResult Settings()
        {
            var viewModel = new SettingsViewModel();

            //get render settings
            var renderVariables = db.RenderVariables.FirstOrDefault();
            viewModel.Quality = renderVariables.Quality;

            //get system settings
            var systemSettings = db.SystemSettings.FirstOrDefault();
            viewModel.SiteTitle = systemSettings.SiteTitle;
            viewModel.SiteDescription = systemSettings.SiteDescription;
            viewModel.SiteKeywords = systemSettings.SiteKeywords;

            return View(viewModel);
        }

        [CheckPermission(section = "Admin")]
        [HttpPost]
        public ActionResult Settings(SettingsViewModel data)
        {
            //update the render settings
            var renderVariables = db.RenderVariables.FirstOrDefault();
            renderVariables.Quality = data.Quality;

            //update the system settings
            var systemSettings = db.SystemSettings.FirstOrDefault();
            systemSettings.SiteTitle = data.SiteTitle;
            systemSettings.SiteDescription = data.SiteDescription;
            systemSettings.SiteKeywords = data.SiteKeywords;

            db.SaveChanges();

            return RedirectToAction("Index");
        }

        [CheckPermission(section = "Admin")]
        public ActionResult PageMeta()
        {
            PageMetaViewModel viewModel = new PageMetaViewModel() ;

            viewModel.Pages = db.PageMetas.ToList().Select(m => new SelectListItem()
            {
                Value = m.PageMetaId.ToString(),
                Text = m.Name
            }).ToList(); 

            return View(viewModel);
        }


        public ActionResult PageMetaByPageMetaId(int pageMetaId)
        {
            var pageMeta = db.PageMetas.Find(pageMetaId);

            if (pageMeta != null)
            {
                return Json(pageMeta);
            }
            else
            {
                return Json("false");
            }

        }

        [HttpPost]
        public ActionResult UpdatePageMeta(int pageMetaId, string title, string keywords, string description)
        {
            var pageMeta = db.PageMetas.Find(pageMetaId);

            if (pageMeta != null)
            {
                pageMeta.Title = title;
                pageMeta.Keywords = keywords;
                pageMeta.Description = description;

                db.SaveChanges();
                return Json("true");
            }
            else
            {
                return Json("false");
            }
        }

        [CheckPermission(section = "Admin")]
        public ActionResult DisplayLog()
        {
            return View();
        }

        [CheckPermission(section = "Admin")]
        public ActionResult GetLogData(string OrderBy, bool Desc)
        {
            var directoryPath = @"C:\inetpub\logs\AdvancedLogs\DEFAULT\ELINIR";

            if (!System.IO.Directory.Exists(directoryPath))
            {
                directoryPath = @"C:\inetpub\logs\AdvancedLogs\ELINIRSCHOOL";
                if (!System.IO.Directory.Exists(directoryPath))
                {
                    return Json(null, JsonRequestBehavior.AllowGet);
                }
            }

            //find the latestLogFile generated by IIS and copy it to the specified directory
            var directory = new DirectoryInfo(directoryPath);
            var latestLogFile = (from f in directory.GetFiles()
                                 orderby f.LastWriteTime descending
                                 select f).First();
            System.IO.File.Copy(latestLogFile.FullName, Server.MapPath("~/weborbLogs/generalLog.log"), true);

            var generalLog = System.IO.File.ReadAllLines(Server.MapPath("~/weborbLogs/generalLog.log"));
            //var weborbReport = System.IO.File.ReadAllLines(Server.MapPath("~/weborbLogs/webOrbLog.txt"));

            var editedRecords = new List<int>();

            //loop through the records in the WeborbLog to match each record with its equlivent log record
            /*foreach (var line in weborbReport)
            {
                var parts = line.Split(' ');
                if (parts.Length > 2)
                {
                    var ip = parts[0];
                    var date = parts[1];
                    var fullTime = parts[2];

                    if (fullTime.Contains("."))
                    {
                        var time = fullTime.Substring(0, fullTime.IndexOf("."));
                        var miliseconds = int.Parse(fullTime.Substring(fullTime.IndexOf(".") + 1));
                        var method = parts[3];

                        //search this string in the generalLog
                        for (var i = 0; i < generalLog.Length; i++)
                        {
                            if (editedRecords.Contains(i) == false)
                            {
                                var logRecord = generalLog[i];

                                if (logRecord.ToLower().Contains("weborb"))
                                {
                                    var recordParts = logRecord.Split(' ');
                                    var recordFullTime = recordParts[2];
                                    var recordMiliseconds = int.Parse(recordFullTime.Substring(recordFullTime.IndexOf(".") + 1));

                                    var searchString = ip + " " + date + " " + time;

                                    if (logRecord.Contains(searchString))
                                    {
                                        if (miliseconds == recordMiliseconds || Math.Abs(miliseconds - recordMiliseconds) <= 150)
                                        {
                                            //append the method to the log
                                            generalLog[i] += " " + method;

                                            i = generalLog.Length;
                                            editedRecords.Add(i);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }*/

            //create JSON object to show log table
            var tableHeaders = new List<string>();
            var tableRows = new List<List<string>>();

            int weborbColIndex = 0;

            //header row (with field names)
            var headerRecord = generalLog.FirstOrDefault(m => m.StartsWith("#Fields:"));
            if (headerRecord != null)
            {
                var headerCols = headerRecord.Replace("#Fields:  ", "").Split(' ');
                foreach (var item in headerCols)
                {
                    tableHeaders.Add(item);
                }
                //tableHeaders.Add("Weborb Method");
            }

            //loop through log records rows
            var logRecords = generalLog.Where(m => m.StartsWith("#") == false);
            foreach (var record in logRecords)
            {
                var tableCols = new List<string>();

                var cols = record.Split(' ');
                for (var i = 0; i < cols.Length; i++)
                {
                    var item = cols[i];

                    if (!string.IsNullOrWhiteSpace(item))
                    {
                        if (i == 1)
                        {
                            item += " " + cols[2];
                        }

                        if (i != 2)
                        {
                            tableCols.Add(item);
                        }
                    }
                }

                //check if there is empty column in the end - add one
                /*weborbColIndex = tableHeaders.IndexOf("Weborb Method");
                if (tableCols.Count <= weborbColIndex)
                {
                    tableCols.Add("-");
                }*/

                //filter out JS/CSS/Images requests from the log
                var filterOutRow = false;
                var urlCol = tableHeaders.IndexOf("cs-uri-stem");
                if (tableCols[urlCol].Contains(".js") || tableCols[urlCol].Contains(".css") || tableCols[urlCol].Contains(".png") || tableCols[urlCol].Contains(".jpg") || tableCols[urlCol].Contains(".gif") || tableCols[urlCol].Contains(".xml") || tableCols[urlCol].Contains(".ico") || tableCols[urlCol].Contains(".woff") || tableCols[urlCol].Contains("GetLogData") || tableCols[urlCol].Contains("GetRenderTasks") || tableCols[urlCol].Contains("GetRenderVariables") || tableCols[urlCol].Contains("IsUserSleeping"))
                {
                    filterOutRow = true;
                }

                if (filterOutRow == false)
                {
                    tableRows.Add(tableCols);
                }
            }

            System.IO.File.Delete(Server.MapPath("~/weborbLogs/generalLog.log"));

            //filter only weborb requests
            /*if (ShowOnlyWeborb)
            {
                tableRows = tableRows.Where(m => m[weborbColIndex] != "-").ToList();
            }*/

            //if there is order column specified
            if (!string.IsNullOrEmpty(OrderBy))
            {
                var colIndex = tableHeaders.IndexOf(OrderBy);
                double chk;

                //if numeric
                if (double.TryParse(tableRows[0][colIndex], out chk))
                {
                    if (!Desc)
                    {
                        tableRows = tableRows.OrderBy(m => double.Parse(m[colIndex])).ToList();
                    }
                    else
                    {
                        tableRows = tableRows.OrderByDescending(m => double.Parse(m[colIndex])).ToList();
                    }
                }
                //if string value
                else
                {
                    if (!Desc)
                    {
                        tableRows = tableRows.OrderBy(m => m.Count > colIndex ? m[colIndex] : "").ToList();
                    }
                    else
                    {
                        tableRows = tableRows.OrderByDescending(m => m.Count > colIndex ? m[colIndex] : "").ToList();
                    }
                }
            }
            //default order
            else
            {
                //order by request date
                var colIndex = tableHeaders.IndexOf("BeginRequest-UTC");
                tableRows = tableRows.OrderByDescending(m => DateTime.Parse(m[colIndex])).ToList();
            }

            var data = new { TableHeaders = tableHeaders, TableRows = tableRows.Take(200) };

            return Json(data, JsonRequestBehavior.AllowGet);
        }
    }
}
